package org.semanticflash.rdf.script
{
	
	import com.bigflexlib.core.markers.IIncomplete;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	import flash.utils.getQualifiedClassName;
	
	import mx.core.IPropertyChangeNotifier;
	import mx.events.PropertyChangeEvent;
	import mx.logging.ILogger;
	import mx.logging.Log;
	
	import org.semanticflash.rdf.values.IRDFValueHolder;
	import org.semanticflash.rdf.values.IRI;
	import org.semanticflash.rdf.values.RDFValue;
	


	[Event(name="propertyChange", type="mx.events.PropertyChangeEvent")]


	use namespace flash_proxy;


	[Bindable]
	/**
	 * 
	 * This is used for quick scripting
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */
	public dynamic class RDFNodeProxy extends Proxy implements IPropertyChangeNotifier, IRDFValueHolder, IIncomplete
	{
		
		
		private var dispatcher:IEventDispatcher;
		

		private var logger:ILogger;
		
		
		private var props:Dictionary = new Dictionary( );		
		
		
		
		private var _node:RDFNode;
		public function get node( ):RDFNode
		{
			return _node;
		}
		
		
		public function get rdfValue():RDFValue
		{
			return _node.rdfValue;
		}
		
		

		
		public function RDFNodeProxy( node:RDFNode )
		{

			_node = node;
			
			dispatcher = new EventDispatcher( this );
			
			logger = Log.getLogger( getQualifiedClassName( this ).split( "::" ).join( "." ) );	
			
		}
		




		private function resolveIRIForPropName( name:* ):IRI
		{
		
			if ( name is QName )
				return IRI.instance3( name as QName );		

			if ( name is IRI )
				return name as IRI;
			
			if ( name is IRDFValueHolder )
				return ( name as IRDFValueHolder ).rdfValue as IRI;
			
			if ( name is String )
				return IRI.instance( name as String );
				

			// TODO: throw error?
		
			return null;

		}




		private function nodeToValue( node:RDFNode ):*
		{
			if ( node == null )
				return undefined;
				
			if ( node is RDFNode )
				return ( node as RDFNode ).proxy;
		
		}


		
		

		///////////////////////////////////////////////////////////////////////////////////////
		/////////////////////////////////// FLASH PROXY ///////////////////////////////////////		
		///////////////////////////////////////////////////////////////////////////////////////



 		override flash_proxy function callProperty( name:*, ... rest ):*
 		{
			var iri:IRI = resolveIRIForPropName( name );
			var result:Array = node.all( iri );
			
			
 		}
 		 

		override flash_proxy function deleteProperty(name:*):Boolean
		{
 			foo();
			return false;
		}


		override flash_proxy function getDescendants( name:* ):* 
		{
		}
		
		

		override flash_proxy function getProperty( name:* ):*
		{
			var iri:IRI = resolveIRIForPropName( name );
			var n:RDFNode = node.any( iri );			
			return nodeToValue( n );
		}
		
		
		
		override flash_proxy function hasProperty( name:* ):Boolean
		{
			var iri:IRI = resolveIRIForPropName( name );
			var n:RDFNode = node.any( iri );			
			return ( n != null );
		}
		
		
		
		override flash_proxy function isAttribute(name:*):Boolean
		{
			foo(); 			
			return false;
		}
		
		
		override flash_proxy function nextName(index:int):String
		{
 			foo();
			return null;
		} 
		
		override flash_proxy function nextNameIndex(index:int):int
		{
 			foo();
			return undefined;
		} 
		
		override flash_proxy function nextValue(index:int):*
		{
 			foo();
		
		}
		
		override flash_proxy function setProperty(name:*, value:*):void
		{
		
 			foo();
		
		} 





		private function foo():void
		{
		
		
		
			 var i:int = 1+1;
		}
		
		
		
		

		

		

		private function setProp( prop:Object, value:* ):void
		{
			var oldValue:* = props[ String( prop ) ];
			props[ String( prop ) ] = value;
			var pce:PropertyChangeEvent = PropertyChangeEvent.createUpdateEvent( this, prop, oldValue, value );
			dispatchEvent( pce );		
		}
		
		
		
		
		///////////////////////////////////////////////////////////////////////////////////////
		//////////////////////////////// IEventDispatcher /////////////////////////////////////		
		///////////////////////////////////////////////////////////////////////////////////////		
		
	    public function addEventListener( type:String, listener:Function,
	    		useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false ):void
	    {
	        dispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference );
	    }
	           
	    public function dispatchEvent( evt:Event ):Boolean
	    {
	        return dispatcher.dispatchEvent(
	        	evt
	        	);
	    }
	    
	    public function hasEventListener(type:String):Boolean{
	        return dispatcher.hasEventListener(type);
	    }
	    
	    public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void{
	        dispatcher.removeEventListener(type, listener, useCapture);
	    }
	                   
	    public function willTrigger(type:String):Boolean {
	        return dispatcher.willTrigger(type);
	    }
		
		
		
		
		
		
		
		
		///////////////////////////////////////////////////////////////////////////////////////
		/////////////////////////////////////// IUID //////////////////////////////////////////		
		///////////////////////////////////////////////////////////////////////////////////////
		/**
		 * this is needed to play the datachange event game...
		*/		
		private var _uid:String;
		public function set uid( uid:String ):void { _uid = uid; }
		public function get uid():String { return _uid; }
				
		
		
		
		
		
		
		
		
	}
	
}

/*
 
 
  callProperty(name:*, ... rest):* 
Overrides the behavior of an object property that can be called as a function. Proxy 
    deleteProperty(name:*):Boolean 
Overrides the request to delete a property. Proxy 
    getDescendants(name:*):* 
Overrides the use of the descendant operator. Proxy 
    getProperty(name:*):* 
Overrides any request for a property's value. Proxy 
    hasProperty(name:*):Boolean 
Overrides a request to check whether an object has a particular property by name. Proxy 
    isAttribute(name:*):Boolean 
Checks whether a supplied QName is also marked as an attribute. Proxy 
    nextName(index:int):String 
Allows enumeration of the proxied object's properties by index number to retrieve property names. Proxy 
    nextNameIndex(index:int):int 
Allows enumeration of the proxied object's properties by index number. Proxy 
    nextValue(index:int):* 
Allows enumeration of the proxied object's properties by index number to retrieve property values. Proxy 
    setProperty(name:*, value:*):void 
Overrides a call to change a property's value. Proxy 
 
 
 
 
 
 */